A distributed computer system typically includes multiple interconnected nodes. On each node in the distributed computer system, one or more applications may be executing through the use of one or more threads, where an application corresponds to a set of computer instructions which may be executed by one or more threads. Further, an application may include of one or more methods. The method may have zero or more input parameters and generates output using the zero or more input parameters. The input parameters may include objects.
Often in a distributed computer system, a method in an application on one node may use the functionality of a method of an application on another node through a remote method invocation (RMI). A RMI allows a method in an application on a source node to request functionality of a target node in a manner similar to a standard method call in which a method calls another method on the same node. Specifically, after the initial steps of connecting the source node to the target node, a thread executing a method in an application on the source node may request a RMI (including the necessary input parameters). Before sending the RMI to the target node, the source node may serialize the objects, if the input parameters of the RMI include objects (i.e., transform the objects into a byte stream).
After the objects are serialized, the objects are sent with the RMI to the target node using protocols known in the art (e.g., Transport Control Protocol (TCP), Internet Protocol (IP)). Upon receiving the RMI, the target node may deserialize the objects. Once the objects are deserialized, the target node may process the RMI by instantiating an instance of the application that includes the method requested in the RMI. After the instance of the application has been instantiated, the method is executed and the result of the executing the method is sent to the application on the source node.
In order to ensure that an application is functioning properly, a debugger may be associated with the application. A debugger is an application that monitors the execution of the application instructions performed by the threads during the execution of the application as well as the state of memory during execution of the application. Thus, the debugger and/or a user is able to determine the points of failure, or bugs, in an application.
When RMIs are used, the debugger associated with the application should be able to determine the instructions performed by the target node as a result of the RMI. Specifically, a debugger should show the execution path (i.e., the instructions performed by multiple nodes which result from the execution of an application on the source node) to enable the user to determine possible points of failure in the execution path. For example, if an application executing on a source node sends a RMI to a target node and fails, the debugger should be able to differentiate between whether the RMI was not sent properly by the application, whether the RMI did not arrive at the target node, whether an error exists at the target node, or whether the result was not able to be received properly.
As a further complication, there are often several threads simultaneously executing the same method on the target node as a result of several RMIs. During execution, remote threads (i.e., the threads on a target node) do not identify the thread(s) on a source node whose initiation of the RMI created the remote threads. Accordingly, debuggers executing on both the source and the target nodes are unable to match the threads executing on the source node with the thread(s) executing on the target node due to the RMI from the source node. Thus, a debugger is unable to determine the instructions performed by the target node as a result of the RMI in order to determine all possible points of failure.
One method for debugging in a distributed computer system having RMIs is for a user to execute the application with the debugger first on the source node. Upon executing the RMI, the debugger may merely log that the RMI is being executed. The user may then execute the method of the RMI on the target node with a separate debugger. In this solution, because the debuggers on the source node and the target node have no means to communicate with each other, the debuggers are unable to match the threads. Accordingly, a user debugging an application on the source node is unable to follow all of the instructions resulting from the application on the source node.